<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | 框架安装
// +----------------------------------------------------------------------

namespace july\julyadmin\install\controller;

use think\facade\Db;

class Install
{
    //资源目录
    private $source_assets_dir = "../vendor/july/julyadmin/data/assets";
    //目标资源目录
    private $to_assets_dir = "./static/assets";

    /**
     * 安装
     * @Author   July
     * @DateTime 2024-01-30T21:04:51+0800
     */
    public function index()
    {
        $install_lock_file = $this->to_assets_dir . '/admin/install.lock';
        if (file_exists($install_lock_file)) {
            die($install_lock_file . '文件已存在,不允许安装');
        }
        //递归复制资源
        $this->installAssets($this->source_assets_dir, $this->to_assets_dir);

        //安装配置文件
        $res = $this->installWebConfig("../vendor/july/julyadmin/src/webconfig");
        if ($res['code'] == 0) {
            die($res['msg']);
        }

        //安装sql文件
        $res = $this->installSql("../vendor/july/julyadmin/sql");
        if ($res['code'] == 0) {
            die($res['msg']);
        }

        $module  = 'admin';
        $app_map = config('app.app_map', []);
        if ($app_map) {
            if ($key = array_search($module, $app_map)) {
                $module = $key;
            }
        }
        file_put_contents($install_lock_file, '这是系统安装锁文件，避免重复装覆盖，删除此文件后可以重新安装覆盖。');
        die('安装成功<br>初始账号：admin<br>初始密码：admin<br><a href="' . url('/' . $module . '/index/login') . '">去登录</a>');
    }

    /**
     * 递归复制静态资源
     * @param  string $source_dir   原资源目录
     */
    public function installAssets($source_dir = "")
    {
        if (!is_readable($this->to_assets_dir)) {
            is_file($this->to_assets_dir) or mkdir($this->to_assets_dir, 0777, true);
            chmod($this->to_assets_dir, 0777);
        }

        $handle = opendir($source_dir);
        while ($file = readdir($handle)) {
            //删除所有文件夹
            $type = filetype($source_dir . "/" . $file);
            if ($file == '.' || $file == "..") {
                continue;
            }

            if ($type == "file") {
                //如果类型为文件
                $source_file = $source_dir . "/" . $file;
                $todir       = str_replace($this->source_assets_dir, $this->to_assets_dir, $source_dir);
                $to_file     = $todir . "/" . $file;
                copy($source_file, $to_file);
            }
            if ($type == "dir") {
                $todir = str_replace($this->source_assets_dir, $this->to_assets_dir, $source_dir) . "/" . $file;
                if (!is_readable($todir)) {
                    is_file($todir) or mkdir($todir, 0777, true);
                    chmod($todir, 0777);
                }
                //如果类型为文件夹
                $this->installAssets($source_dir . "/" . $file);
            }
        }
        closedir($handle);
    }

    /**
     * 安装配置文件
     * @Author   July
     * @DateTime 2024-01-30T20:55:33+0800
     * @return   array                                   ['code'=>1|0,'msg'=>'']
     */
    private function installWebConfig($webconfig_path = '')
    {
        $to_webconfig_path = '../webconfig';
        if (!is_readable($to_webconfig_path)) {
            is_file($to_webconfig_path) or mkdir($to_webconfig_path, 0777, true);
            chmod($to_webconfig_path, 0777);
        }

        try {
            $files = scandir($webconfig_path);
            foreach ($files as $key => $file) {
                if ($file !== '.' && $file !== '..') {
                    copy($webconfig_path . DIRECTORY_SEPARATOR . $file, $to_webconfig_path . '/' . $file);
                }
            }
            return ['code' => 1, 'msg' => '配置文件安装成功'];
        } catch (\Think\Exception $e) {
            return ['code' => 0, 'msg' => $e->getMessage()];
        }

    }

    /**
     * 安装sql文件
     * @Author   July
     * @DateTime 2024-01-28T12:02:58+0800
     * @param    string                   $sql_dir  sql文件目录
     * @return   array                    ['code'=>1|0,'msg'=>'']
     */
    private function installSql($sql_path = '')
    {
        $default = config('database.default');
        if (!$default) {
            $default = 'mysql';
        }
        if ($default !== 'mysql') {
            return ['code' => 0, 'msg' => '当前连接的数据库不是mysql'];
        }
        $database = config('database.connections.mysql');
        if (!$database) {
            return ['code' => 0, 'msg' => 'database.connections.mysql不存在'];
        }
        if (!isset($database['username']) || !$database['username']) {
            return ['code' => 0, 'msg' => '数据库用户名不能为空'];
        }
        if (!isset($database['password']) || !$database['password']) {
            return ['code' => 0, 'msg' => '数据库用户名不能为空'];
        }
        if (!isset($database['database']) || !$database['database']) {
            return ['code' => 0, 'msg' => '数据库名不能为空'];
        }

        try {
            $files    = scandir($sql_path);
            $default  = config('database.default');
            $config   = config('database.connections.' . $default);
            $instance = Db::connect($default);
            $instance->getTables();
            foreach ($files as $key => $file) {
                if ($file !== '.' && $file !== '..') {
                    $sql      = file_get_contents($sql_path . DIRECTORY_SEPARATOR . $file);
                    $sql      = preg_replace('~//(.*)+\n~', '', $sql);
                    $patterns = [
                        '/\-\-.*?\n/', // 单行注释（--）
                        '/#[^\r\n]*/', // #号后面的内容为注释
                        '/\/\*.*?\*\/|\/\/.*/s', /**///注释
                        '/SET FOREIGN_KEY_CHECKS = ([\d]+);/',
                    ];
                    $sql = preg_replace($patterns, '', $sql);
                    //给表名加上前缀
                    $sql  = preg_replace(['/DROP TABLE IF EXISTS `([a-zA-Z_\d]+)`;/s'], 'DROP TABLE IF EXISTS `' . $database['prefix'] . '$1`;', $sql);
                    $sql  = preg_replace(['/CREATE TABLE `([a-zA-Z_\d]+)`/s'], 'CREATE TABLE `' . $database['prefix'] . '$1`', $sql);
                    $sql  = preg_replace(['/INSERT INTO `([a-zA-Z_\d]+)`/s'], 'INSERT INTO `' . $database['prefix'] . '$1`', $sql);
                    $sql  = preg_replace(['/UPDATE `([a-zA-Z_\d]+)` SET/s'], 'UPDATE `' . $database['prefix'] . '$1` SET', $sql);
                    $sql  = preg_replace(['/DELETE FROM `([a-zA-Z_\d]+)`/s'], 'DELETE FROM `' . $database['prefix'] . '$1`', $sql);
                    $sqls = array_filter(explode('\r\n;', $sql));
                    foreach ($sqls as $sql_k => $sql_v) {
                        $patterns = ['/\r\n/'];
                        $sql      = preg_replace($patterns, '', $sql_v);
                        $instance->getPdo()->exec($sql);
                    }
                }
            }
            return ['code' => 1, 'msg' => 'sql安装成功'];
        } catch (\Think\Exception $e) {
            return ['code' => 0, 'msg' => $e->getMessage()];
        }
    }
}
